﻿using System;
using System.Globalization;
using System.Windows.Forms;
using QAToolsAddin.GenericDialogs;
using QAToolsAddin.GenericDialogs.Fields;
using Excel = Microsoft.Office.Interop.Excel;

namespace QAToolsAddin.UI {
    class Conv {
        private readonly Excel.Application _excelapp;
        private Excel.Range _range;
        private CultureInfo _culture;

        public Conv(Excel.Application application, CultureInfo culture) {
            try {
                _excelapp = application;
                _culture = culture;
                _range = application.ActiveWindow.RangeSelection;
            } catch (Exception ex) { new FrmException(_excelapp, ex).ShowDialog(); }
        }

        public void ClearNumberFormat() {
            try {
                foreach (Excel.Range area in _range.Areas) {
                    var range = _excelapp.Intersect(area, area.Worksheet.UsedRange);
                    Undo.AddUndoArea(range);
                    range.NumberFormat = "";
                }
            } catch (Exception ex) { new FrmException(_excelapp, ex).ShowDialog(); }
        }

        public void ToText() {
            try {
                foreach (Excel.Range area in _range.Areas) {
                    var range = _excelapp.Intersect(area, area.Worksheet.UsedRange);
                    if (range == null) continue;
                    _excelapp.ScreenUpdating = false;
                    var clipBackup = Clipboard.GetText();
                    Undo.AddUndoArea(range);
                    range.Copy(Type.Missing);
                    var data = System.Windows.Forms.Clipboard.GetText();
                    range.Application.CutCopyMode = 0;
                    range.NumberFormat = "@";
                    System.Windows.Forms.Clipboard.SetText(data);
                    range.PasteSpecial();
                    Clipboard.Clear();
                    if (string.IsNullOrEmpty(clipBackup) == false)
                        Clipboard.SetText(clipBackup);
                }
            } catch (Exception ex) {
                new FrmException(_excelapp, ex).ShowDialog();
            } finally {
                _excelapp.ScreenUpdating = true;
            }
        }

        public void ToText2() {
            try {
                foreach (Excel.Range area in _range.Areas) {
                    var range = _range.Application.Intersect(area, area.Worksheet.UsedRange);
                    if (range == null) continue;
                    int nbRow = range.Rows.Count;
                    int nbCol = range.Columns.Count;
                    var array = ExcelArray<string>.Create(nbRow, nbCol);
                    Undo.AddUndoArea(range);
                    for (int r = 1; r <= nbRow; r++) {
                        for (int c = 1; c <= nbCol; c++)
                            array[r, c] = (string)((Excel.Range)range.Cells[r, c]).Text;
                    }
                    range.NumberFormat = "@";
                    range.Formula = array;
                }
            } catch (Exception ex) { new FrmException(_excelapp, ex).ShowDialog(); }
        }

        public void ToText3() {
            try {
                new CellsOperator(_range).ForEachValue("@", delegate(ref object value) {
                    string text;
                    if (Parser.ToText(value, _culture, out text))
                        value = text;
                });
            } catch (Exception ex) { new FrmException(_excelapp, ex).ShowDialog(); }
        }

        public void ToEmptyText() {
            try {
                new CellsOperator(_range, true).ForEachValue(null, delegate(ref object value) {
                    if (value == null)
                        value = "'";
                });
            } catch (Exception ex) { new FrmException(_excelapp, ex).ShowDialog(); }
        }

        public void ToNumber() {
            int defautIndex = _culture.NumberFormat.NumberDecimalSeparator == "." ? 0 : 1;
            var f0 = new FieldRadioBT("From format", new string[] { "Period", "Comma" }, "Decimal separator", defautIndex);
            var f1 = new FieldCheckBox("Extract from non digit characters", "Extract the number from strings Ex: 'a1'=>'1'", true, true);
            var f2 = new FieldCheckBox("Set empty cells to 0", "Set 0 to empty cells Ex: ''=>'0'", true, true);
            var f3 = new FieldCheckBox("Set cell to 0 on failure", "Set 0 when the parsing fails Ex: 'abc'=>'0'", false, true);
            new InputBox(_excelapp, "To number", f0, f1, f3, f2).Show(delegate {
                char decimalSeparator = f0.Value == 0 ? '.' : ',';
                bool zeroOnEmpty = f2.Value;
                bool zeroOnFailure = f3.Value;
                bool extract = f1.Value;
                new CellsOperator(_range, true).ForEachValue("", delegate(ref object value) {
                    if (value == null) {
                        if (zeroOnEmpty)
                            value = 0d;
                    } else {
                        double number;
                        if (Parser.ToNumber(value, decimalSeparator, extract, out number))
                            value = number;
                        else if (zeroOnFailure)
                            value = 0;
                    }
                });
            });
        }

        public void ToValue() {
            try {
                new CellsOperator(_range).ForEachValue(null, delegate(ref object value) { });
            } catch (Exception ex) { new FrmException(_excelapp, ex).ShowDialog(); }
        }

        public void ToBoolean() {
            try {
                new CellsOperator(_range).ForEachValue("", delegate(ref object value) {
                    bool boolean;
                    if (Parser.ToBoolean(value, out boolean))
                        value = boolean;
                });
            } catch (Exception ex) { new FrmException(_excelapp, ex).ShowDialog(); }
        }


        public void ToTime() {
            try {
                new CellsOperator(_range).ForEachValue("[$-F400]hh:mm:ss", delegate(ref object value) {
                    System.DateTime datetime;
                    if (Parser.ToDateTime(value, _culture, out datetime))
                        value = new System.DateTime(1899, 12, 30, datetime.Hour, datetime.Minute, datetime.Second);
                });
            } catch (Exception ex) { new FrmException(_excelapp, ex).ShowDialog(); }
        }

        public void ToDate() {
            var f0 = new FieldRadioVertical("From format", "", new string[] { _culture.EnglishName, "English Day / Month", "English Month / Day" }, 0, true);
            new InputBox(_excelapp, "To Date", f0).Show(delegate {
                CultureInfo culture = null;
                switch (f0.Value) {
                    case 0: culture = _culture; break;
                    case 1: culture = CultureInfo.GetCultureInfo("en-gb"); break;
                    case 2: culture = CultureInfo.GetCultureInfo("en-us"); break;
                }
                var format = "m/d/yyyy";
                //var format = _culture.DateTimeFormat.ShortDatePattern;
                new CellsOperator(_range).ForEachValue(format, delegate(ref object value) {
                    System.DateTime datetime;
                    if (Parser.ToDateTime(value, culture, out datetime))
                        value = new System.DateTime(datetime.Year, datetime.Month, datetime.Day);
                });
            });
        }

        public void ToDateTime() {
            var f0 = new FieldRadioVertical("From format", "", new string[] { _culture.EnglishName, "English Day / Month", "English Month / Day" }, 0, true);
            new InputBox(_excelapp, "To DateTime", f0).Show(delegate {
                CultureInfo culture = null;
                switch (f0.Value) {
                    case 0: culture = _culture; break;
                    case 1: culture = CultureInfo.GetCultureInfo("en-gb"); break;
                    case 2: culture = CultureInfo.GetCultureInfo("en-us"); break;
                }
                //var format = "m/d/yyyy hh:mm;@";
                var format = _culture.DateTimeFormat.ShortDatePattern + " HH:mm";
                new CellsOperator(_range).ForEachValue(format, delegate(ref object value) {
                    System.DateTime datetime;
                    if (Parser.ToDateTime(value, culture, out datetime))
                        value = datetime;
                });
            });
        }

        public void ToAmount() {
            try {
                string format = Utils.GetCurrencyFormat(_culture.LCID, _culture.NumberFormat.CurrencySymbol, _culture.NumberFormat.CurrencyPositivePattern);
                char decimalSeparator = _culture.NumberFormat.CurrencyDecimalSeparator[0];
                new CellsOperator(_range).ForEachValue(format, delegate(ref object value) {
                    decimal currency;
                    if (Parser.ToCurrency(value, decimalSeparator, out currency))
                        value = currency;
                });
            } catch (Exception ex) { new FrmException(_excelapp, ex).ShowDialog(); }
        }

    }
}
